package ro.msg.quiz.repository;

import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Scanner;

import javax.swing.JOptionPane;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 
 * @author Vlad,Roxana This class is repository of questions.
 */
@XmlRootElement(name = "questions")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class RepositoryQuestion {
	// an array list containing all the questions
	private ArrayList<Question> questionsList;

	/**
	 * Constructor
	 */
	public RepositoryQuestion() {
		this.setQuestionsList(new ArrayList<Question>());

	}

	/**
	 * Constructor
	 * 
	 * @param questionsList
	 *            The list of questions.
	 */
	public RepositoryQuestion(ArrayList<Question> questionsList) {
		this.setQuestionsList(questionsList);
		// readFromFileQuestions();
		// writeToFileQuestions();
	}

	/**
	 * 
	 * @return Returns the list of questions.
	 */
	@XmlElement(name = "question")
	public ArrayList<Question> getQuestionsList() {
		return questionsList;
	}

	/**
	 * Sets the list of questions to repository.
	 * 
	 * @param questionsList
	 *            The list of questions to be set.
	 */
	public void setQuestionsList(ArrayList<Question> questionsList) {
		this.questionsList = questionsList;
	}

	/**
	 * @param id
	 *            The id of question.
	 * @return Returns an object of type Question with a given id, or if it
	 *         doesn't exist it returns null.
	 */
	public Question getQuestion(int id) {
		for (Question question : questionsList) {
			if (question.getId() == id)
				return question;
		}
		return null;
	}

	/**
	 * This method append a question to the list.
	 * 
	 * @param question
	 *            The question to be appended to list.
	 */
	public void addQuestion(Question question) {
		this.questionsList.add(question);
	}

	/**
	 * This method deletes a question from list.
	 * 
	 * @return Returns true if the question was successfully deleted or false if
	 *         the question did not exist.
	 */
	public boolean deleteQuestion(int id) {
		for (Iterator<Question> it = questionsList.iterator(); it.hasNext();) {
			Question question = it.next();
			if (question.getId() == id) {
				it.remove();
				return true;
			}
		}
		return false;
	}

	/**
	 * This method edits a single choice question with a specific id. First it
	 * searches if the id exists in repository and is of type SingleChoiceQ.
	 * 
	 * @param id
	 *            The id of question.
	 * @param text
	 *            The text of question.
	 * @param options
	 *            The options of question.
	 * @param correctOption
	 *            The correct options of question.
	 * @return Returns true if the question was edited or false if fail.
	 */
	public boolean editSingleChoiceQ(int id, String text,
			ArrayList<String> options, int correctOption) {
		Question question = this.getQuestion(id);
		if (question != null)
			if (question instanceof SingleChoiceQ) {
				question.setText(text);
				((SingleChoiceQ) question).setCorrectOption(correctOption);
				((SingleChoiceQ) question).setOptions(options);
				DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
				Date date = new Date();
				question.setLastEdited(dateFormat.format(date));
				return true;
			}
		return false;
	}

	/**
	 * This method edits a multiple choice question with a specific id. First it
	 * searches if the id exists in repository and is of type MultipleChoiceQ.
	 * 
	 * @param id
	 *            The id of question.
	 * @param text
	 *            The text of question.
	 * @param noOfOptions
	 *            The number of options of question.
	 * @param options
	 *            The options of question.
	 * @param correctOptions
	 *            The correct options of question.
	 * @return Returns true if the question was edited or false if fail.
	 */
	public boolean editMultipleChoiceQ(int id, String text, int noOfOptions,
			ArrayList<String> options, ArrayList<Integer> correctOptions) {
		Question question = this.getQuestion(id);
		if (question != null)
			if (question instanceof MultipleChoiceQ) {
				question.setText(text);
				((MultipleChoiceQ) question).setCorrectOptions(correctOptions);
				((MultipleChoiceQ) question).setNoOfOptions(noOfOptions);
				((MultipleChoiceQ) question).setOptions(options);
				DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
				Date date = new Date();
				question.setLastEdited(dateFormat.format(date));
				return true;
			}
		return false;
	}

	/**
	 * /** This method edits a text question with a specific id. First it
	 * searches if the id exists in repository and is of type TextQ.
	 * 
	 * @param id
	 *            The id of question.
	 * @param text
	 *            The text of question.
	 * @param answer
	 *            The answer of question.
	 * @return Returns true if the question was edited or false if fail.
	 */
	public boolean editTextQ(int id, String text, String answer) {
		Question q = this.getQuestion(id);
		if (q != null)
			if (q instanceof TextQ) {
				q.setText(text);
				q.setText(text);
				((TextQ) q).setAnswer(answer);
				DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
				Date date = new Date();
				q.setLastEdited(dateFormat.format(date));
				return true;
			}
		return false;
	}

	/**
	 * 
	 * @return Returns the iterator of question
	 */
	public Iterator<Question> QuestionIterator() {
		return questionsList.iterator();
	}

	/**
	 * This method reads from txt file.
	 */
	public void readFromFileQuestions(String path) {

		Scanner sc = null;

		try {
			sc = new Scanner(new FileReader(path + "\\questions.txt"));
			String line = "";
			String lineParsed = "";
			int id = 0, type = 0, correctIndex = 0;
			String question = "";
			String answer = "";
			ArrayList<String> listOption;
			while (sc.hasNextLine()) {
				listOption = new ArrayList<String>();
				line = sc.nextLine();
				String[] attr = line.split("[ ]");
				id = Integer.parseInt(attr[0]);
				type = Integer.parseInt(attr[1]);
				lineParsed = "";
				for (int i = 2; i < attr.length; i++) {
					lineParsed += attr[i] + " ";
				}
				lineParsed = lineParsed.replaceAll("' '", ";");
				lineParsed = lineParsed.replaceAll("'", ";");
				lineParsed = lineParsed.replaceAll("; ", ";");
				String[] attrLineParsed = lineParsed.split("[;]");
				question = attrLineParsed[1];
				if (type == 3) {
					// listOption.clear();
					answer = attrLineParsed[3];
					Question quest1 = new TextQ(id, question, answer);
					quest1.setLastEdited(attrLineParsed[2]);
					this.questionsList.add(quest1);

				} else if (type == 1) {
					// listOption.clear();
					for (int j = 3; j < attrLineParsed.length - 1; j++) {
						listOption.add(attrLineParsed[j]);

					}
					correctIndex = Integer.parseInt(attr[attr.length - 1]);
					Question quest2 = new SingleChoiceQ(id, question,
							listOption, correctIndex);
					quest2.setLastEdited(attrLineParsed[2]);
					this.questionsList.add(quest2);
				} else if (type == 2) {
					// listOption.clear();
					for (int j = 3; j < attrLineParsed.length - 1; j++) {
						listOption.add(attrLineParsed[j]);
					}
					int noOfOptions = listOption.size();
					String line3 = "";
					int usedPartsOfLine = 3;
					line3 = attrLineParsed[usedPartsOfLine + noOfOptions];
					ArrayList<Integer> correctIndexList = new ArrayList<Integer>();
					String[] l = line3.split("[ ]");
					for (int j = 1; j <= l.length - 1; j++) {
						Integer correctIndexPart = Integer.parseInt(l[j]);
						correctIndexList.add(correctIndexPart);
					}
					Question quest3 = new MultipleChoiceQ(id, question,
							noOfOptions, listOption, correctIndexList);
					quest3.setLastEdited(attrLineParsed[2]);
					this.questionsList.add(quest3);
				}
			}

		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.toString(),
					"Error - QuestionIn", JOptionPane.WARNING_MESSAGE);
		}
	}

	/**
	 * This method writes to file questionsOut.txt.
	 */
	public void writeToFileQuestions(String path) {

		BufferedWriter bufferedWriter = null;
		try {
			bufferedWriter = new BufferedWriter(new FileWriter(path
					+ "\\questions.txt"));
			for (int i = 0; i < questionsList.size(); i++) {
				Question questionq = questionsList.get(i);
				bufferedWriter.write(Integer.toString(questionq.getId()) + " "
						+ Integer.toString(questionq.getType()) + " '"
						+ questionq.getText() + "' '"
						+ questionq.getLastEdited() + "' ");
				for (String s : questionq.getOptions()) {
					bufferedWriter.write("'" + s + "' ");
				}
				for (String s : questionq.getAnswers()) {
					bufferedWriter.write(s + " ");
				}
				bufferedWriter.newLine();
			}
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.toString(),
					"Error - QuestionOut", JOptionPane.WARNING_MESSAGE);
		} finally {
			try {
				bufferedWriter.close();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, e.toString(),
						"Error - QuestionOut", JOptionPane.WARNING_MESSAGE);
			}
		}
	}
}
